﻿# define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//int main()
//{
//	const int n = 0;
//	printf("n = %d\n", n);
//	int* p = &n;
//	*p = 666;
//	printf("n = %d\n", n);
//	return 0;
//}


//int main()
//{
//	const int a = 666;
//	const int* const p = &a;
//	*p = 0;//err
//	int b = 888;
//	p = &b;//err
//	printf("a=%d\n", a);
//	
//	return 0;
//}

//#include <stdio.h>
////指针+- 整数
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = &arr[0];
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(p + i));//p+i 这⾥就是指针+整数
//	}
//	return 0;
//}


////指针-指针
//#include <stdio.h>
//int strl(char* s)
//{
//	char* pa = s;
//	while (*pa != '\0')
//		pa++;
//	return pa - s;
//}
//int main()
//{
//	printf("%d\n", strl("abcef"));
//	return 0;
//}

////指针的关系运算
//#include <stdio.h>
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* pa = &arr[0];
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	while (pa < arr + sz) //指针的⼤⼩⽐较
//	{
//		printf("%d ", *pa);
//		pa++;
//	}
//	return 0;
//}



//#include <stdio.h>
//int main()
//{
//	int* p;//局部变量指针未初始化，默认为随机值
//	*p = 20;
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = &arr[0];
//	int i = 0;
//	for (i = 0; i <= 11; i++)
//	{
//		//当指针指向的范围超出数组arr的范围时，p就是野指针
//		*(p++) = i;
//	}
//	return 0;
//}


//#include <stdio.h>
//int* test()
//{
//	int a = 666;
//	return &a;
//}
//int main()
//{
//	int* pa = test();
//	printf("%d\n", *pa);
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	int num = 666;
//	int* p1 = &num;
//	int* p2 = NULL;
//	assert(p2 != NULL);
//	printf("haha\n");
//	return 0;
//}

//#include <stdio.h>
//#include <assert.h>
//
//int divide(int a, int b) {
//    assert(b != 0);  // 断言：除数不能为0
//    return a / b;
//}
//
//int main() {
//    int a = 10;
//    int b = 0;
//
//    int result = divide(a, b);
//    printf("Result: %d\n", result);
//
//    return 0;
//}
//#include <stdio.h>
//
//#include <string.h>
//
//
//
//void counter_clockwise(char* start, char* end)
//
//{
//
//	while (start < end)
//
//	{
//
//		int temp = *start;
//
//		*start = *end;
//
//		*end = temp;
//
//		start++;
//
//		end--;
//
//	}
//
//}
//
//
//
//void reve(char* arr2, int str, int count)
//
//{
//
//	counter_clockwise(arr2, arr2 + count - 1);// 翻转前k个字符
//
//	counter_clockwise(arr2 + count, arr2 + str - 1); // 翻转剩余的字符
//
//	counter_clockwise(arr2, arr2 + str - 1);// 整体翻转
//
//
//
//}
//
//
//
//int main()
//
//{
//
//	int k = 0;
//	char arr1[5] = "ABCD";
//	int len = sizeof(arr1) / sizeof(arr1[0]) - 1;
//	scanf("%d", &k);
//	reve(arr1, len, k);
//	printf("%s", arr1);
//	return 0;
//}

//int main()
//{
//	int a = 0;
//	char s1[] = "AABCD";
//	char s2[]="abcd"
//	return 0;
//}
//
// 






// 
// 
//写一个函数，判断一个字符串是否为另外一个字符串旋转之后的字符串。
//例如：给定s1 = AABCD和s2 = BCDAA，返回1
//给定s1 = abcd和s2 = ACBD，返回0.
//
//AABCD左旋一个字符得到ABCDA
//AABCD左旋两个字符得到BCDAA
//AABCD右旋一个字符得到DAABC



动态内存分布，不过会经过缓冲区有警告！
警告分析；
这个警告C6386是Microsoft Visual Studio编译器的一个静态代码分析器（Static Code Analyzer）给出的警告。
这个警告表示在写入temp时，可能发生了缓冲区溢出，即写入的数据超出了temp所分配的内存空间。
在你的代码中，temp是通过malloc函数动态分配的内存空间，大小为2* len1 + 1个字节。
然而，警告指出可能写入了2个字节的数据，这超出了所分配的内存空间。
这个警告的原因可能是在你的代码中存在一些潜在的缓冲区溢出问题，例如在对temp进行写入时，没有足够的检查来确保不会超出分配的内存空间。
这可能导致程序在运行时发生未定义行为，例如覆盖了其他内存区域的数据，或者导致程序崩溃。
//#include <stdio.h>
//
//#include <string.h>
//#include <stdlib.h>
//
//int isRotatedString(char* s1, char* s2) 
//{
//    int len1 = strlen(s1);
//    int len2 = strlen(s2);
//
//    if (len1 != len2) 
//    {
//        return 0;
//    }
//
//    char* temp = (char*)malloc(2 * len1 + 1);
//    if (temp == NULL) 
//    {
//        return 0; // Memory allocation failed
//    }
//
//    int i, j;
//    for (i = 0; i < len1; i++) 
//    {
//        temp[i] = s1[i];
//    }
//    for (j = 0; j < len1; j++) 
//    {
//        temp[i + j] = s1[j];
//    }
//    temp[i + j] = '\0';
//
//    for (i = 0; i < len1; i++) 
//    {
//        int matched = 1;
//        for (j = 0; j < len1; j++) 
//        {
//            if (s2[j] != temp[(i + j) % len1]) 
//            {
//                matched = 0;
//                break;
//            }
//        }
//        if (matched) 
//        {
//            free(temp);
//            return 1;
//        }
//    }
//    free(temp);
//    return 0;
//}
//
//int main() 
//{
//    char s1[] = "AABCD";
//    char s2[] = "BCDAA";
//    printf("%d\n", isRotatedString(s1, s2)); // Output: 1
//
//    char s3[] = "abcd";
//    char s4[] = "ACBD";
//    printf("%d\n", isRotatedString(s3, s4)); // Output: 0
//
//    return 0;
//}

修改动态内存方法，不发出警告，不让缓冲区溢出
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int isRotatedString(char* s1, char* s2) {
    int len1 = strlen(s1);
    int len2 = strlen(s2);

    if (len1 != len2) {
        return 0;
    }

    char* temp = (char*)malloc(2 * len1 + 1);
    if (temp == NULL) {
        return 0; // Memory allocation failed
    }

    // 使用strcat函数将s1连接到temp上
    strcpy(temp, s1);
    strcat(temp, s1);

    for (int i = 0; i < len1; i++) {
        int matched = 1;
        for (int j = 0; j < len1; j++) {
            if (s2[j] != temp[(i + j) % len1]) {
                matched = 0;
                break;
            }
        }
        if (matched) {
            free(temp);
            return 1;
        }
    }
    free(temp);
    return 0;
}

int main() {
    char s1[] = "AABCD";
    char s2[] = "BCDAA";
    printf("%d\n", isRotatedString(s1, s2)); // Output: 1

    char s3[] = "abcd";
    char s4[] = "ACBD";
    printf("%d\n", isRotatedString(s3, s4)); // Output: 0

    return 0;
}


第二种方法>>>>使用strcpy; strcat函数

#include <stdio.h>
#include <string.h>

int isRotatedString(char* s1, char* s2) {
    int len1 = strlen(s1);
    int len2 = strlen(s2);

    if (len1 != len2) {
        return 0;
    }

    char temp[2 * len1 + 1];
    strcpy(temp, s1);
    strcat(temp, s1);

    if (strstr(temp, s2) != NULL) {
        return 1;
    }
    else {
        return 0;
    }
}

int main() {
    char s1[] = "AABCD";
    char s2[] = "BCDAA";
    printf("%d\n", isRotatedString(s1, s2)); // Output: 1

    char s3[] = "abcd";
    char s4[] = "ACBD";
    printf("%d\n", isRotatedString(s3, s4)); // Output: 0

    return 0;
}





//在C语言中，常量字符串是存储在只读内存区域的，因此不能直接通过指针来修改它们的值。如果尝试修改常量字符串的值，会导致编译器报错或者程序崩溃。
//另外，常量字符串的位置也是固定的，不能直接通过指针来调换它们的位置。常量字符串是存储在只读内存区域的，所以无法直接修改它们的位置。
//如果需要在程序中对字符串进行读写操作或者调换它们的位置，可以使用字符数组来代替常量字符串。字符数组是可以修改和调换位置的，但需要注意数组越界和内存访问权限的问题。

void levoduction(char* p, int k, int sz)
{//错误写法
    for (int i = 0; i < k; i++)
    {
        for (int j = 0; j < sz - 1; j++)
        {
            char tmp = *(p + j);
            *(p + j) = *(p + j + 1);
            *(p + j + 1) = tmp;
        }
    }
}
int main()
{
    char* p = "abcd";
    int sz = strlen(p);
    int k = 0;
    scanf("%d", &k);
    levoduction(p, k, sz);
    printf("%s");
    return 0;
}
字符串
真正正确的做法为：
int Reverse_order(char* arr1, char* arr2)
{
	int len1 = strlen(arr1);
	int len2 = strlen(arr2);
	if (len1 != len2)
	{
		return 0;
	}
	char* temp = (char*)malloc(2 * len1 + 1);
	if (NULL==temp)
	{
		return 0;
	}
	//1,错误；堆栈，缓冲区无法写入
	//int i = 0;
	//for (i = 0; i <len1 ; i++)
	//{
	//	temp[i] = arr1[i];
	//}
	//int j = 0;
	//for (j = 0; j < len2; i++)
	//{
	//	temp[i + j] = arr1[j];
	//}
	//temp[i + j] = '\0';
	strcpy(temp, arr1);
	strcat(temp, arr1);
	int i = 0;
	for (i = 0; i < len1; i++)
	{
		int Flag = 1;
		int j = 0;
		for (j = 0; j < len2; j++)
		{
			if (arr2[j] != temp[(i+j)%len1])
			{
				Flag = 0;
				break;
			}
		}
		if (Flag)
		{
			free(temp);
			return 1;
		}
	}
	free(temp);
	return 0;
}

int main()
{
	char s1[] = "AABCD";
	char s2[] = "BCDAA";
	int ret = Reverse_order(s1,s2);
	printf("%d\n", ret);

	char s3[] = "abcd";
	char s4[] = "ACBD";
	int set = Reverse_order(s3, s4);
	printf("%d", set);

	return 0;
}






在屏幕上打印杨辉三角。

由于此题要打印整个杨辉三角的数据而非取出某一项，所以不可避免的一定是要填出每一项，没有偷懒的余地，那就老老实实的根据规律填空即可。
按照题设的场景，能发现数字规律为：d[i][j] = d[i - 1][j] + d[i - 1][j - 1]。
所以我们只要按照这个方法填表即可


1

1 1

1 2 1

1 3 3 1

……
第一方法：
void yangHuiTriangle(int n)
{
    int data[30][30] = { 1 }; //第一行直接填好，播下种子

    int i, j;

    for (i = 1; i < n; i++) //从第二行开始填
    {
        data[i][0] = 1; //每行的第一列都没有区别，直接给1，保证不会越界。
        for (j = 1; j <= i; j++) //从第二列开始填
        {
            data[i][j] = data[i - 1][j] + data[i - 1][j - 1]; //递推方程
        }
    }

    for (i = 0; i < n; i++) //填完打印
    {
        for (j = 0; j <= i; j++)
        {
            printf("%d ", data[i][j]);
        }
        putchar('\n');
    }
}



//第二方法：

改进：
由于我在填第n行的杨辉三角时，只跟第n - 1行的杨辉三角产生联系，不会跟之前的有联系，
所以没必要保存每一行的杨辉三角，填一行打一行就行了，这样能让空间复杂度从n ^ 2降低到n。
但是在填数据的时候不能对之前的数据覆盖，所以需要从后向前填。而填杨辉三角顺序对结果是没有影响的，所以可以实现。

void yangHuiTriangle(int n)
{
    int data[30] = { 1 };

    int i, j;
    printf("1\n"); //第一行就直接打印了
    for (i = 1; i < n; i++) //从第二行开始
    {
        for (j = i; j > 0; j--) //从后向前填，避免上一行的数据在使用前就被覆盖
        {
            data[j] += data[j - 1]; //公式同上，由于变成了一维，公式也变简单了。
        }

        for (j = 0; j <= i; j++) //这一行填完就直接打印了。
        {
            printf("%d ", data[j]);
        }
        putchar('\n');
    }
}

※这种方法虽然降低了空间复杂度，但只能保存最后一行的数据，不利于反复查询，两个填法各有各的适用场景。就本题而言，改进后的胜出。


//第三方法：
这段代码首先会要求用户输入要打印的杨辉三角的行数，然后使用两个嵌套的循环来打印每一行的数字。
外层循环控制行数，从0开始递增到用户输入的行数。内层循环控制每一行的数字的个数，从0开始递增到当前行数。
在每一行的开始，先使用一个循环打印一定数量的空格，用来使得每一行的数字居中对齐。
然后使用另一个循环来计算并打印每个数字。在每一行中，第一个数字和最后一个数字都是1，其他数字的计算基于上一行的数字。具体计算方法是通过组合数公式计算当前数字的值。
最后，在每一行打印完所有的数字后，使用一个换行符来换行，以便打印下一行的数字。
这样，当外层循环结束后，就会在屏幕上打印出所需行数的杨辉三角。

#include <stdio.h>
int main() {
    int rows, coef = 1, space, i, j;

    printf("Enter the number of rows: ");
    scanf("%d", &rows);

    for (i = 0; i < rows; i++) {
        for (space = 1; space <= rows - i; space++) {
            printf("  ");
        }

        for (j = 0; j <= i; j++) {
            if (j == 0 || i == 0) {
                coef = 1;
            }
            else {
                coef = coef * (i - j + 1) / j;
            }

            printf("%4d", coef);
        }

        printf("\n");
    }

    return 0;
}



第四种方法：
在这个程序中，首先要求用户输入要打印的行数，然后使用两个循环来打印杨辉三角。外层循环控制打印的行数，
内层循环控制每一行的数字。在内层循环中，使用变量c来保存杨辉三角中的数字，每次打印c的值，
然后根据杨辉三角的规律更新c的值
#include <stdio.h>
int main() {
    int n = 0;
    int i = 0;
    int j = 0;
    int c = 0;

    printf("请输入要打印的行数：");
    scanf("%d", &n);

    for (i = 0; i < n; i++)
    {
        c = 1;
        for (j = 0; j <= i; j++)
        {
            printf("%d ", c);
            c = c * (i - j) / (j + 1);//规律法
        }
        printf("\n");
    }

    return 0;
}


//猜凶手
//
//日本某地发生了一件谋杀案，警察通过排查确定杀人凶手必为4个嫌疑犯的一个。
//
//以下为4个嫌疑犯的供词:
//
//A说：不是我。
//
//B说：是C。
//
//C说：是D。
//
//D说：C在胡说
//
//已知3个人说了真话，1个人说的是假话。
//
//现在请根据这些信息，写一个程序来确定到底谁是凶手。
int main()
{
	int Flag = 0;// 记录说真话的人数
	char murderer ;// 记录凶手

	for (char suspect = 'A'; suspect <= 'D'; suspect++)
	{
		int count = 0;// 每个嫌疑犯说真话的数量
		if (suspect != 'A')
		{
			count++;
		}
		if (suspect == 'C')
		{
			count++;
		}
		if (suspect == 'D')
		{
			count++;
		}
		if (suspect != 'D')
		{
			count++;
		}
		if (3 == count)
		{
			Flag ++;
			murderer = suspect;
		}
	}
	if (1 == Flag)// 只有一个人说了真话
	{
		printf("%c\n", murderer);
	}
	else
	{
		printf("没找到\n");
	}
	return 0;
}



杨氏矩阵

有一个数字矩阵，矩阵的每行从左到右是递增的，矩阵从上到下是递增的，请编写程序在这样的矩阵中查找某个数字是否存在。
要求：时间复杂度小于O(N);
我的做法：
第一种》》》》

二分查找，
突破口为每个右上角的最大的数
int matrix(int arr2[4][4], int target)
{
	int row = 0;
	int line = 3;
	while (row < 4 || line >= 0)
	{
		if (arr2[row][line] == target)
		{
			return 1;
		}
		else if (arr2[row][line] > target)
		{
			line--;
		}
		else
		{
			row++;
		}
	}
	return 0;
}
int main()
{
	int arr1[][4] =
	{
		{1,3,5,7},
		{2,4,6,8},
		{9,10,11,12},
		{13,15,17,19},
	};
	int find = 0;
	scanf("%d", &find);
	int ret = matrix(arr1, find);
	if (ret)
	{
		printf("找到了\n");
	}
	else
	{
		printf("没找到\n");
	}

	return 0;
}


指针数组错题：
如何定义一个int类型的指针数组，数组元素个数为10个：()我选了C
A.int a[10]
B.int(*a)[10]
C.int* a[10];
D.int (*a[10])(int);
题目要int的指针数组，A为int数组，B为int数组的指针，
C为int的指针数组，D为int(*)(int)函数指针的数组，故选C


//下面哪个是指针数组：（ ）我选了D
                        //错了
A. int* arr[10];
B.int* arr[];
C.int** arr;
D.int(*arr)[10];

//指针数组是一个数组，该数组的每个元素是一个指针

A：正确，定义了一个数组，该数组中有10个元素，每个元素都是int* 的指针类型
B：错误，编译失败，定义数组时，要给出空间的大小，如果没有给时，必须要给出初始化结果
C：错误，定义了一个二级指针
D：错误，* 和arr先结合，说明arr不是数组。实际上arr是一个指针，一个指向数组的指针。
因此：选择A


//关于数组指针的描述正确的是：（    ）


作业内容
A.数组指针是一种数组
B.数组指针是一种存放数组的指针
C.数组指针是一种指针
D.指针数组是一种指向数组的指针

AD缩句后分别是：指针是数组、数组是指针，自相矛盾。B选项说的有问题，数组指针存放的是数组的地址，而非数组本身。故选C。